﻿using System;
using System.Collections.Generic;
using JTLeigh.Commerce.Spencer.Core.Common;
using JTLeigh.Commerce.Spencer.Core.Common.Services;
using JTLeigh.Commerce.Spencer.Features.ProductImages.Business.Caches;
using JTLeigh.Commerce.Spencer.Features.ProductImages.Common;
using JTLeigh.Commerce.Spencer.Features.ProductImages.Common.Entities;
using JTLeigh.Commerce.Spencer.Features.ProductImages.Data.Providers;
using Microsoft.Practices.Unity;

namespace JTLeigh.Commerce.Spencer.Features.ProductImages.Business.Services
{

	/// <summary>
	/// An <see cref="IProductImageService"/> implementation that gets product images from the 
	/// database with caching.
	/// </summary>
	public class ProductImageService : IProductImageService
	{

		#region Properties

		/// <summary>
		/// Gets or sets the product image provider to use to get product images from the database.
		/// </summary>
		/// <value>An <see cref="IProductImageProvider"/> implementation.</value>
		[Dependency]
		public IProductImageProvider ProductImageProvider { get; set; }

		/// <summary>
		/// Gets or sets the product image cache to use to cache product images.
		/// </summary>
		[Dependency]
		public IProductImageCache ProductImageCache { get; set; }

		/// <summary>
		/// Gets or sets the exception handling service to use to handle exceptions.
		/// </summary>
		/// <value>An <see cref="IExceptionHandlingService"/> implementation.</value>
		[Dependency]
		public IExceptionHandlingService ExceptionHandlingService { get; set; }

		#endregion // Properties

		#region IProductImageService Members

		/// <summary>
		/// Gets a dictionary of product images by product identifier and culture identifier.
		/// </summary>
		/// <param name="tenantId">The tenant identifier <see cref="Guid"/> of the tenant whose
		/// images are to be retrieved.</param>
        /// <param name="catalogId">The catalog identifier <see cref="String"/> of the catalog
        /// that the product whose images are to be retrieved is in.</param>
        /// <param name="productId">The product identifier <see cref="String"/> of the product 
		/// whose images are to be retrieved.</param>
		/// <param name="cultureId">The <see cref="Int32"/> LCID of the culture to use to retrieve
		/// culture-specific resources.</param>
		/// <returns>A <see cref="Dictionary{TKey,TValue}"/> of <see cref="LocalizedProductImage"/> 
		/// keyed by image identifier <see cref="Guid"/>.</returns>
		public Dictionary<Guid, LocalizedProductImage> GetProductImages(Guid tenantId, string catalogId, string productId, int cultureId)
		{
			Dictionary<Guid, ProductImage> images;
			Dictionary<Guid, LocalizedProductImage> localizedImages;
			LocalizedProductImage localizedImage;
			ProductImageLocalization localization;

            Safety.AssertArgumentNotNull("catalogId", catalogId);
			Safety.AssertArgumentNotNull("productId", productId);

			try
			{
				images = GetProductImagesWithCaching(tenantId, catalogId, productId);
				localizedImages = new Dictionary<Guid, LocalizedProductImage>();
				foreach (ProductImage image in images.Values)
				{
					image.Localizations.TryGetValue(cultureId, out localization);
					localizedImage = new LocalizedProductImage(image, localization);
					localizedImages.Add(image.ImageId, localizedImage);
				}
				return localizedImages;
			}
			catch (Exception e)
			{
				ExceptionHandlingService.HandleException(tenantId, e, ProductImagesExceptionPolicy.Business);
				throw;
			}
		}

		#endregion // IProductImageService Members

		#region Implementation

		private Dictionary<Guid, ProductImage> GetProductImagesWithCaching(Guid tenantId, string catalogId, string productId)
		{
			Dictionary<Guid, ProductImage> images;

            Safety.AssertArgumentNotNull("catalogId", catalogId);
            Safety.AssertArgumentNotNull("productId", productId);

			images = ProductImageCache.GetProductImages(tenantId, catalogId, productId);
			if (images == null)
			{
				images = ProductImageProvider.GetProductImages(tenantId, catalogId, productId);
				ProductImageCache.SetProductImages(tenantId, catalogId, productId, images);
			}
			return images;
		}

		#endregion // Implementation

	}

}
